<template>
  <n-space vertical>
    <n-card v-if="showSearch">
      <z-form
        ref="searchFormRef"
        :schemas="searchSchemas ?? []"
        :form-props="searchFormProps"
        :form-action-span="searchFormActionSpan"
        submitActionText="查询"
        :formItemGap="16"
        @submit="searchHandler"
        @reset="$emit('searchReset')"
      >
      </z-form>
    </n-card>

    <n-card>
      <template #header>
        <slot name="title" v-if="$slots.title" :methods="tableMethods"></slot>
        <z-icon-tip
          v-else
          :content="title"
          :tooltip="titleHelp"
          :placement="titleHelpPlacement"
          :icon="titleHelpTriggerIcon"
        />
      </template>

      <template #header-extra>
        <n-space>
          <slot
            name="header"
            v-if="$slots.header"
            :methods="tableMethods"
          ></slot>
          <template v-if="showTools">
            <!-- table refetch -->
            <n-button tertiary @click="tableMethods.fetchDataSource">
              <z-icon name="RefreshIcon"></z-icon>
            </n-button>
            <!-- TODO: table tools -->
            <n-button tertiary>
              <z-icon name="SettingsIcon"></z-icon>
            </n-button>
          </template>
        </n-space>
      </template>
      <n-data-table v-bind="nTableProps" />
    </n-card>
  </n-space>
</template>

<script setup lang="ts">
import { PopoverPlacement, FormProps } from "naive-ui";
import { computed, onMounted, ref } from "vue";
import { ZFormItemSchema } from "@/components/Form/typings";
import ZForm from "@/components/Form/ZForm.vue";
import { ZIconName } from "@/components/Icon";
import { INDEX_COLUMN_TITLE } from "./hooks/columns";
import { emptyDataSourceApi, useTableCore } from "./hooks/core";
import { ExtendedDataTableProps, ZTableColumn, ZTableMethods } from "./typings";

export interface ZTableProps {
  tableProps: ExtendedDataTableProps;

  searchSchemas?: ZFormItemSchema[];
  searchFormProps?: FormProps;
  searchFormActionSpan?: number;
  reloadAfterSearch?: boolean;
  title?: string;
  titleHelp?: string | string[];
  titleHelpTriggerIcon?: ZIconName;
  titleHelpPlacement?: PopoverPlacement;
  indexColumn?: boolean;
  indexColumnTitle?: string;
  // generally it's 0 OR 1.
  indexColumnOffset?: number;
  // current page's row index OR total's row index.
  indexColumnIncreaseWithPage?: boolean;
  // render your own actions here; usually for CRUD buttons.
  actionColumn?: Omit<ZTableColumn, "key">;
  // dataSource api to replace ${tableProps.data}
  dataSourceApi?: (...args: any[]) => Promise<unknown>;
  // fields Config
  listField?: string;
  totalField?: string;
  pageField?: string;
  limitField?: string;
  // how sorter would be conveyed to remote
  getSorterParams?: (sorter: any) => any;
}

const props = withDefaults(defineProps<ZTableProps>(), {
  searchSchemas: () => [],
  searchFormProps: () => ({
    labelPlacement: "left",
  }),
  searchFormActionSpan: 8,
  reloadAfterSearch: true,
  title: "",
  titleHelp: "",
  titleHelpPlacement: "right",
  titleHelpTriggerIcon: "InformationIcon",
  indexColumn: false,
  indexColumnTitle: INDEX_COLUMN_TITLE,
  indexColumnOffset: 1,
  indexColumnIncreaseWithPage: true,
  actionColumn: undefined,
  dataSourceApi: emptyDataSourceApi,
  listField: "list",
  totalField: "total",
  pageField: "page",
  limitField: "limit",
  getSorterParams: (s: any) => s,
});

const showSearch = computed(() => !!props.searchSchemas?.length);
const showTools = computed(() => false);

const searchFormRef = ref();
const { nTableProps, tableMethods } = useTableCore(props, searchFormRef);

onMounted(() => {
  tableMethods.fetchDataSource();
});

/* emits */
const emit = defineEmits<{
  (event: "searchSubmit", values: unknown, tableMethods: ZTableMethods): void;
  (event: "searchReset"): void;
}>();

const searchHandler = (values: unknown) => {
  emit("searchSubmit", values, tableMethods);
  if (props.reloadAfterSearch) {
    tableMethods.reload();
  }
};

/* expose */
defineExpose(tableMethods);
</script>
